json 模块
Python 内置的 json 模块主要提供 4 个常用方法,可以分成两组记忆:
| 方法 | 作用 | 操作对象 |
|---|---|---|
json.dumps() | Python 对象 → JSON 字符串 | 内存中的字符串 |
json.loads() | JSON 字符串 → Python 对象 | 内存中的字符串 |
json.dump() | Python 对象 → JSON 文件 | 文件 |
json.load() | JSON 文件 → Python 对象 | 文件 |
记忆技巧:带 s 的处理字符串 string,不带 s 的处理文件。
1. json.dumps():对象转 JSON 字符串
import json
data = {"name": "张三", "age": 30, "tags": ["python", "ai"]}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)
输出:
{
"name": "张三",
"age": 30,
"tags": [
"python",
"ai"
]
}
常用参数:
ensure_ascii=False:保留中文,不转成\uXXXX。indent=2:缩进美化输出。sort_keys=True:按 key 排序。default=func:处理不可序列化的对象,比如datetime。
2. json.loads():JSON 字符串转对象
import json
json_str = '{"name": "Bob", "age": 25, "skills": ["java", "linux"]}'
obj = json.loads(json_str)
print(obj["name"]) # Bob
print(obj["skills"][0]) # java
如果字符串不是合法 JSON,会抛出 json.JSONDecodeError。
3. json.dump():对象写入 JSON 文件
import json
data = {"product": "Laptop", "price": 8999, "in_stock": True}
with open("product.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
它不会返回字符串,而是直接写入文件。
4. json.load():从文件读取 JSON
import json
with open("product.json", "r", encoding="utf-8") as f:
obj = json.load(f)
print(obj)
print(type(obj)) # <class 'dict'>
类型对应关系
Python 和 JSON 之间会做这些自动转换:
| Python | JSON |
|---|---|
dict | object |
list / tuple | array |
str | string |
int / float | number |
True | true |
False | false |
None | null |
进阶用法
自定义序列化(default)
json 只支持基础类型,遇到 datetime、自定义对象等会抛 TypeError。default 接收一个函数,遇到无法序列化的对象时调用它,返回可序列化的结果:
import json
from datetime import datetime
def to_json(obj):
if isinstance(obj, datetime):
return obj.strftime("%Y-%m-%d %H:%M:%S")
raise TypeError(f"不支持序列化: {type(obj)}")
json.dumps({"time": datetime.now()}, default=to_json)
# '{"time": "2026-10-23 16:30:00"}'
简单场景直接 default=str 也可以:json.dumps({"time": datetime.now()}, default=str)。
自定义反序列化(object_hook)
object_hook 接收一个函数,每解析完一个 JSON object 都会调用它,适合在读取时做定制转换:
import json
def hook(d):
if "date" in d:
d["date"] = d["date"].replace("-", "/")
return d
obj = json.loads('{"date": "2026-10-23"}', object_hook=hook)
# {'date': '2026/10/23'}
编码器/解码器类
需要复用同一套配置、或通过继承定制行为时,用 JSONEncoder / JSONDecoder:
import json
from datetime import datetime
# 编码器:复用配置
encoder = json.JSONEncoder(ensure_ascii=False, sort_keys=True)
encoder.encode({"b": 2, "a": 1}) # '{"a": 1, "b": 2}'
decoder = json.JSONDecoder()
decoder.decode('{"a": 1}') # {'a': 1}
# 继承定制:处理 datetime
class MyEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, datetime):
return o.isoformat()
return super().default(o)
json.dumps({"time": datetime.now()}, cls=MyEncoder)
日常用 dumps / loads 传参数即可,类只在复用或深度定制时使用。
异常处理
json.loads 遇到非法 JSON 抛 json.JSONDecodeError;dumps 遇到不可序列化对象抛 TypeError。读取外部数据时建议捕获:
import json
try:
obj = json.loads("不是合法json")
except json.JSONDecodeError as e:
print(f"解析失败: {e.msg}, 第 {e.lineno} 行第 {e.colno} 列")
附:with open 怎么理解
json.dump() / json.load() 操作文件时,推荐写法都是 with open(...) as f。这一行包含两部分:
open(...):打开文件,返回文件对象
open("product.json", "r", encoding="utf-8")
| 参数 | 值 | 意思 |
|---|---|---|
| 第 1 个(文件路径) | "product.json" | 要打开的文件 |
| 第 2 个(模式 mode) | "r" | read,只读(默认值);"w" 写入覆盖、"a" 追加 |
encoding | "utf-8" | 按UTF-8 解码字节 → 文字,避免中文乱码 |
返回值是一个文件对象,是后续读写操作的"遥控器",此时还没有读取内容。
with ... as f:自动关闭文件
with 的作用:代码块结束时自动执行 f.close(),即使中途报错也会关闭。
不用 with 的等价写法:
f = open("product.json", "r", encoding="utf-8")
try:
obj = json.load(f)
finally: # 无论成功失败都要手动关闭
f.close()
用 with 简化为:
with open("product.json", "r", encoding="utf-8") as f:
obj = json.load(f)
# 离开 with 代码块时,f 自动 close,不需要写 f.close()
as f 就是给文件对象起名字,在缩进代码块内通过 f 使用它。
常见注意
- 不能直接序列化
datetime、自定义对象、文件对象等,需要用default自定义转换。 - 读取外部 JSON 时要做好异常处理,避免解析失败导致程序崩溃。
- 中文数据建议始终加上
ensure_ascii=False,否则中文会变成\uXXXX。